home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 10
/
FM Towns Free Software Collection 10.iso
/
ms_dos
/
tool
/
mercury
/
idxfile.c
< prev
next >
Wrap
Text File
|
1995-02-10
|
7KB
|
332 lines
/*
MercuryInstaller IDXファイル読み込みルーチン
Copyright (c) Delmonta
*/
#include<stdio.h>
#include<stdarg.h>
#include<string.h>
#include<stdlib.h>
#include<dos.h>
#include<farstr.h>
#include<ctype.h>
#include"mercury.h"
/*---------------------------------定数と型----------------------------------*/
typedef enum
{
DRIVE,KEYWORD,PROGRAM,MAKE,DIR,MANUAL,README,COPY,XCOPY,COMMANDNUM,
NULLLINE=COMMANDNUM,
} COMMAND_T;
/*-----------------------------グローバル変数--------------------------------*/
static char *Filename=NULL; /* 読み込み中のファイル名 */
static int Linepos; /* 現在の行番号 */
static char *Command[COMMANDNUM] = /* .idxファイルの各パラメータ */
{
"DRIVE","KEYWORD","PROGRAM","MAKE","DIR","MANUAL","README",
"COPY","XCOPY"
};
/*---------------------------エラーを出力して終了----------------------------*/
/* メニュー画面ができあがる前の段階だから、単にメッセージを出力して終了するだ*/
/* けでよい */
/*---------------------------------------------------------------------------*/
static void die(char *s,...)
{
va_list ap;
va_start(ap,s);
if (Filename!=NULL)
fprintf(stderr,"%s %d:",Filename,Linepos);
vfprintf(stderr,s,ap);
putc('\n',stderr);
exit(1);
}
/*---------------------------ファイルのオープン------------------------------*/
static FILE *xfileopen(char *filename)
{
FILE *fp=fopen(filename,"r");
if (fp==NULL)
die("%sが見つかりません",filename);
Filename = filename;
printf("%sを読み込み中です ",filename);
return fp;
}
/*-----------------------エラー処理を含むメモリ管理--------------------------*/
static char ERR_NOMEM[] = "メモリ不足です";
static void far *farmalloc_die(size_t size)
{
void far *p = far_sbrk(size);
if (p==NULL)
die(ERR_NOMEM);
return p;
}
static void far *farcalloc_die(size_t size)
{
void far *p = farmalloc_die(size);
far_memset(p,'\0',size);
return p;
}
static void *nearmalloc_die(size_t size)
{
void *p = malloc(size);
if (p==NULL)
die(ERR_NOMEM);
return p;
}
static char *nearstrdup_die(char *s)
{
s = strdup(s);
if (s==NULL)
die("dead from nearstrdup");
return s;
}
static char far *farstrdup_die(char *s) /* sはfarポインタではない */
{
size_t a = strlen(s)+1;
char far *p = farmalloc_die(a);
far_memcpy(p,s,a);
return p;
}
/*---------------------------Dataの未定義情報の整理--------------------------*/
static void data_storeall(void)
{
Datanum++;
if ((Datanum & 63)==0)
putchar('.');
if (Data->make==NULL)
Data->make = "";
if (Data->keywords==0)
die("検索キーワードが指定されていません");
#if 0
if (Data->dir==NULL && Data->copy==NULL)
die("データのディレクトリを指定してください");
/* サークル紹介データのように、マニュアルだけのものも*/
/* あるかもしれないのでこの警告を出すかどうかは保留 */
#endif
}
/*-----------------------------KEYWORDコマンド-------------------------------*/
static void cmd_keyword(char *p)
{
if (Datanum<0)
{
for (p=strtok(p,Separators) ; p!=NULL ;
p=strtok(NULL,Separators) )
{
if (Keywordnum >= MEMBERSOF(Keyword))
die("キーワードの数が多すぎます");
Keyword[Keywordnum++] = nearstrdup_die(p);
}
}
else
{
int i;
KEYWORD_T f = 0;
for (p=strtok(p,Separators) ; p!=NULL ;
p=strtok(NULL,Separators) )
{
for (i=0 ; i<Keywordnum ; i++)
{
if (strcmp(Keyword[i],p)==0)
{
f |= 1UL<<i;
goto nexttoken;
}
}
die("不正なキーワードです:%s",p);
nexttoken:
;
}
Data->keywords = f;
}
}
/*------------------------------PROGRAMコマンド------------------------------*/
static void cmd_program(char *s)
{
struct DATA far *data = farcalloc_die(sizeof(struct DATA));
if (Datanum>=0) /* 最初のPROGRAM指定ではない */
{
data_storeall();
data->next = Data;
}
else
{
data->next = NULL;
Datanum = 0;
}
Data = data;
Data->title = farstrdup_die(strchop(s,TITLEWIDTH));
}
/*----------------------------COPY/XCOPYコマンド-----------------------------*/
static void cmd_copy(char *s,bool isxcopy)
{
struct COPYDATA_T far *p = farmalloc_die(sizeof(struct COPYDATA_T));
p->string = farstrdup_die(s);
p->isxcopy = isxcopy;
p->next = Data->copy;
Data->copy = p;
}
/*----------------------------トークンの切り出し-----------------------------*/
static COMMAND_T getcommand(char *buf,char **next)
{
int i;
char *p,*q;
while (isspace(*buf))
buf++;
if (*buf=='\0')
return NULLLINE;
if ((p=strchr(buf,':'))==NULL)
die("コマンドが不正です:%s",buf);
q = p+1;
while (isspace(*q))
q++;
*next = q;
do
p--;
while (isspace(*p));
*++p = '\0';
p = strchr(q,'\n');
if (p)
*p = '\0';
for (i=0 ; i<MEMBERSOF(Command) ; i++)
{
if (strcmp(buf,Command[i])==0)
goto end;
}
if (Flag_noignore)
die("不正なコマンドです:%s\n",buf);
else
return NULLLINE;
end:
return (COMMAND_T)i;
}
/*-----------------------------メインルーチン--------------------------------*/
extern void readidxfile(char *filename)
{
FILE *fp = xfileopen(filename);
COMMAND_T code;
int flag = 0; /* コマンドの二重指定を防ぐためのフラグ */
char buf[512];
char *s;
Datanum = -1;
Linepos = 0;
if (Drive=='\0')
{
if (filename[1]==':')
Drive = filename[0];
else
Drive = bdos(0x19,0,0) + 'A'; /* カレントドライブ */
}
while (fgets(buf,sizeof(buf),fp)!=NULL)
{
Linepos++;
code = getcommand(buf,&s);
if (code==NULLLINE)
continue;
if (Datanum<0 && code>PROGRAM)
die("PROGRAMコマンドの前に%sコマンドがあります\n",
Command[code]);
if (flag & (1<<code))
die("%sコマンドが2回指定されています",Command[code]);
switch (code)
{
case KEYWORD:
cmd_keyword(s);
break;
case PROGRAM:
cmd_program(s);
flag = 0;
break;
case MAKE:
flag |= 1<<MAKE;
Data->make = farstrdup_die(strchop(s,MAKEWIDTH));
break;
case DIR:
flag |= 1<<DIR;
Data->dir = farstrdup_die(s);
break;
case COPY:
case XCOPY:
cmd_copy(s,code);
break;
case README:
flag |= 1<<README;
Data->readme = farstrdup_die(s);
break;
case MANUAL:
flag |= 1<<MANUAL;
Data->manual = farstrdup_die(s);
break;
case DRIVE:
if (isalpha(*s))
Drive=*s;
else
die("不正なドライブ名です:%s\n",s);
break;
}
}
fclose(fp);
data_storeall();
putchar('.');
putchar('\n');
}
/*----------------------------End of idxfile.c-------------------------------*/